#include "udp_io_client.h"
#ifdef WIN32
#define usleep(x) Sleep(x)
#endif
#include "Log.h"

UdpIOClient::UdpIOClient(std::string paddr/*="127.0.0.1"*/,int pport/*=60004*/
    ,std::string laddr/*="127.0.0.1"*/,int lport/*=0*/)
    : running(true)
{
    acl_lib_init();
    queuefor_record = QueueDataSingle<RecordItem>::getInstance();
    char  local[64]={0}, peer[64]={0};
	snprintf(local, sizeof(local), "%s:%d",laddr.c_str(),lport);
    local_addr = std::string(local);
    snprintf(peer, sizeof(peer), "%s:%d",paddr.c_str(),pport);
    peer_addr = std::string(peer);
}

UdpIOClient::~UdpIOClient()
{
    running = false;
}

void* UdpIOClient::run()
{
    ACL_VSTREAM *stream = acl_vstream_bind(local_addr.c_str(), 2, 0);  /* 绑定 UDP 套接口 */
    if (stream == NULL) {
		CLogger::createInstance()->Log(MsgError,"acl_vstream_bind %s error %s in UdpIOClient::run()",
			local_addr.c_str(), acl_last_serror());
		return NULL;
	}
    printf("bind udp addr %s ok\r\n", local_addr.c_str());
    //
    acl_vstream_set_peer(stream, peer_addr.c_str());
	ACL_VSTREAM_SET_RWTIMO(stream, 1);

    unsigned char  buf[256] = {0};
    int ret = 0, dlen=0;
	while (running)
    {
        dlen = getBuf(buf,256);
        if(dlen>0)
        {
            // printf("getBuf sucess:%d\n",dlen);
            ret = acl_vstream_write(stream, buf, dlen);
            if (ret == ACL_VSTREAM_EOF) {
                printf("acl_vtream_write error %s\r\n",
                    acl_last_serror());
                //重置udp
                acl_vstream_close(stream);
                stream = acl_vstream_bind(local_addr.c_str(), 2, 0);  /* 绑定 UDP 套接口 */
                if (stream == NULL) 
                {
                    CLogger::createInstance()->Log(MsgError,"acl_vstream_bind %s error %s in UdpIOClient::run()",
                        local_addr.c_str(), acl_last_serror());
                    break;
                }
            }
            // else{
            //     //
            //     printf("acl_vtream_write sucess:\n");
            //     for (int i = 0; i < dlen; i++)
            //     {
            //         printf("%02X", buf[i]);
            //     }
            //     printf("\n");
            // }
        }
        usleep(10);
    }
    
    acl_vstream_close(stream);
    return NULL;
}

int UdpIOClient::getBuf(unsigned char* buf, int size)
{
    int ret = -1;
    std::queue<RecordItem> its;
	if (queuefor_record->getList(its,10))
    {
        if (NULL != buf) 
        {
            int idx = 0;

            buf[idx++] = static_cast<unsigned char>(0xF8);		//0-STX
            //信息长度
            buf[idx++] = static_cast<unsigned char>(0xf0);		//1-Len_L
            buf[idx++] = static_cast<unsigned char>(0xf0);		//2-Len_H
            //数据个数
			buf[idx++] = 0x00;		//size_L
			buf[idx++] = 0x00;		//size_H
            int sizeW = 0;
			while (!its.empty())
            {
                RecordItem item = its.front();
                //devid
                buf[idx++] = static_cast<unsigned char>(item.devid & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.devid >> 8) & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.devid >> 16) & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.devid >> 24) & 0xff);
                //
                //pid
                buf[idx++] = static_cast<unsigned char>(item.pid & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.pid >> 8) & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.pid >> 16) & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.pid >> 24) & 0xff);
                //time
                buf[idx++] = static_cast<unsigned char>(item.sec & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.sec >> 8) & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.sec >> 16) & 0xff);
                buf[idx++] = static_cast<unsigned char>((item.sec >> 24) & 0xff);
                //ms
                buf[idx++] = (unsigned char)(item.usec & 0xFF);		//毫秒值
                //val
                unsigned char*vavch = (unsigned char*)&(item.val);
                buf[idx++] = vavch[3];
                buf[idx++] = vavch[2];
                buf[idx++] = vavch[1];
                buf[idx++] = vavch[0];
                vavch = NULL;
                // printf("send -> %d,%d,%d,%d,%.2f\n",item.devid,item.pid,item.sec,item.usec,item.val);
                sizeW += 1;//实际写入长度
                its.pop();
            }
            //comment len
            buf[1] = static_cast<unsigned char>(idx & 0xff);
            buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);
            //ponit size
			buf[3] = static_cast<unsigned char>(sizeW & 0xff);
			buf[4] = static_cast<unsigned char>((sizeW >> 8) & 0xff);

            unsigned char m_end = 0xFF;
            memcpy(buf + idx, &m_end, 1);
            idx++;
            
            // printf("send len(%d):\n", idx);
			// for (int i = 0; i < idx; i++)
			// {
			// 	printf("%02X", buf[i]);
			// }
			// printf("\n");
            return idx;
        }
    }
    return ret;
}